package com.zpark.cloud.alibaba.controller;

import com.alibaba.csp.sentinel.Entry;
import com.alibaba.csp.sentinel.SphO;
import com.alibaba.csp.sentinel.SphU;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import com.zpark.cloud.alibaba.sentinel.SentinelControllerSentinelResources;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;

/**
 * @PackageName: com.zpark.cloud.alibaba.controller
 * @ClassName: SentinelFlowLimitController
 * @Description:
 * @author: RZS
 * @date: 2023/6/21  9:45
 */
@RestController
@RequestMapping("/sentinel")
public class SentinelFlowLimitController {

    @GetMapping("/testA")
    public String testA() {
        return testASphU();
    }

    @GetMapping("/testB")
    public String testB() {
        return testBBySphO();
    }

    @GetMapping("/testC")
    @SentinelResource(value = "TestBSentinelResources", fallback = "testCFallBack",
    fallbackClass = SentinelControllerSentinelResources.class)
    public String testC() {
        return "<h1>TestC服务访问成功</h1>";
    }

    @GetMapping("/testD")
    @SentinelResource(value = "TestDRule", fallback = "TestBSentinelResources",
    fallbackClass = SentinelControllerSentinelResources.class)
    public String testD() {
        // 初始化流控规则
        initFlowRule();

        return "<h1>testD处理请求</h1>";
    }


    /**
     * 通过代码定义流量控制规则
     */
    public static void initFlowRule(){
        // 定义流控规则
        // 定义loadRules方法所需的参数
        List<FlowRule> rules = new ArrayList<>();
        // 定义一个限流规则对象
        FlowRule rule = new FlowRule();
        // 设置资源名称
        rule.setResource("TestDRule");
        // 设置限流阈值的类型
        rule.setGrade(RuleConstant.FLOW_GRADE_QPS);
        // 设置QPS的阈值为2
        rule.setCount(2);


        // 添加限流规则对象
        rules.add(rule);

        // 定义限流规制
        FlowRuleManager.loadRules(rules);
    }

    /**
     * 通过 SphU 手动定义资源
     * @return
     */
    public String testASphU(){
        Entry entry = null;

        try {
            entry = SphU.entry("testABySphU");
            // 处理逻辑代码....
            return "<h1>testASphU处理请求</h1>";
        } catch (BlockException e) {
            e.printStackTrace();
            return "<h1>testA 服务被限流</h1>";
        } finally {
            if (entry != null) {
                entry.exit();
            }
        }
    }

    /**
     * 通过 SphO 手动定义资源
     */
    public String testBBySphO(){
        if (SphO.entry("testBSphO")) {
            // 务必保证finally会被执行
            try {
                /**
                 * 限流逻辑
                 */
                return "<h1>服务访问成功------testB：</h1>";
            } finally {
                SphO.exit();
            }
        }else {
            // 资源访问阻止，被限流或被降级
            //流控逻辑处理 - 开始
            return "<h1>testB 服务被限流</h1>";
            //流控逻辑处理 - 结束
        }
    }
}
